在Spring源码剖析的前三篇文章,我们介绍了ApplicationContext、Bean相关内容、BeanPostProcessor的内容;但从普遍反馈和自己事后阅读的体验来看,文章过长,没有重点,条理并不是特别清楚。想必是写作方式出了问题,最突出的莫过于流水账式写法,虽然写作的目的并不一定是写出好的文章,而是主要服务自己,但时间一长,自己也是个普通的读者,同样会看不大懂。

因此,写作方法是需要变更了:要突出条理和重点,如需大段源码讲解,可在文章最后增加源码解析一节,读者可选读。也就是说,长度还是那么长,但可读性增强了很多。

本文我们关注SpringBoot启动时做了什么,这是理解自动注解的基础,下一篇文章我们将探索自动注解的实现方式。

一个最简单的SpringBoot应用,可以是这样

1
2
3
4
5
6
@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
SpringApplication(MyApplication::class.java).run(*args)
}

那么重点落在SpringApplication类和其run方法上。

SpringApplication

SpringApplication是一个大类,包含了所有应用启动流程。包含的主要步骤如下

  • 创建ApplicationContext
  • 注册CommandLinePropertySourceEnvironment,用于将命令行参数暴露成容器中的属性值
  • 刷新容器,即调用容器的refresh()方法
  • 创建CommandLineRunner并调用其run()方法

关键点

  • SpringApplication能够启动三种类型的应用

    • 普通的Servlet应用
    • 响应式的Reactive应用
    • 普通的非Web应用

    不同的应用,会创建对应的ApplciationContext实现类,在ApplicationContext源码分析那一节有所描述

  • SpringApplication引入了一个新的临时容器,BootstrapperBootstrapRegistry,用于在创建出ApplicationContext实例之前管理启动阶段的Bean

  • SpringApplication提供ApplicationContextInitializer接口,用于在ApplicationContext刷新前修改它,这为我们提供了一个自定义ApplicationContext的扩展点。

    向SpringApplication注册它的方式有两个

    • 调用SpringApplication.addInitializers()方法手动注册,手写代码时候可用
    • 放在META-INF/spring.factories中,自定义starter时可用
  • SpringApplication的核心 —— META-INF/spring.factories,启动时,会从所有jar包的该文件中搜寻指定factory类型的实现,SpringBoot的诸多特性,比如自动配置,都是依赖于该机制实现。加载该文件有专门的类——SpringFactoriesLoader。在SpringApplication中,加载的类有四种

    • Bootstrapper:SpringBoot启动阶段用
    • ApplicationContextInitializer:Spring上下文初始化器
    • SpringApplicationRunListener:SpringApplication启动时候的监听器
    • ApplicationListener:Spring事件监听器

    这其中最重要的当属ApplicationContextInitializer,考虑到其能力,SpringBoot的诸多功能应该都是由其子类实现。

    如果我们要查看哪些初始化器生效了,可以去对应jar包的spring.factories下查看。比如要看自动配置,去spring-boot-autoconfigure包下的spring.factories文件下查看(我们将在下一篇文章研究这个)

SpringApplication提供的自定义点

SpringApplication启动时也支持高级写法,可自定义更多内容,再run,比如

1
2
3
4
5
6
7
fun main(args: Array<String>) {
// 先创建SpringApplication实例,再设置该实例,自定义一些内容
springApplicationContext = SpringApplication(MylogApplication::class.java).run {
addInitializers(MylogApplication())
run(*args)
}
}

这是除了spring.factories外,Spring为我们提供了的额外定义方法,主要可自定义如下内容:

  • 主类
  • WebApplicationType
  • 是否允许Bean覆盖
  • Bean是否延迟加载
  • Banner的模式:不显示、显示在控制台、显示在日志中
  • 命令行参数否写入Spring环境
  • 是否将ApplicationConversionService添加到ApplicationContext的转换服务中
  • 添加Bootstrapper
  • 添加BootstrapRegistryInitializer
  • 设置默认属性,会被添加到环境变量中
  • 设置额外的profile
  • 设置BeanNameGenerator
  • 设置ConfigurableEnvironment
  • 添加其它需要被添加到容器的资源,主要是指Configuration的资源
  • 设置ResourceLoader
  • 设置环境变量前缀,当从系统中获取环境变量时,将会应用该前缀
  • 设置ConfigurableApplicationContext,相当于手动指定容器的类型了
  • 设置ApplicationContextFactory
  • 设置ApplicationContextInitializer,即添加自定义的初始化器
  • 添加ApplicationListener,即事件监听器
  • 设置ApplicationStartup,该类并没有什么用,仅日志输出用

还缺啥

如上,加上后面的源码分析,我们只看到了SpringApplication的启动流程,貌似并没有看到关键之所在

  • application.properties配置文件的加载原理
  • 自动配置加载的原理

这些其实在spring-boot.jarspring-boot-autoconfigure.jar中的META-INF/spring.factories有指定,出于篇幅,我们下篇文章再讨论。

源码分析

这次源码分析我们单独放在一边

构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public SpringApplication(Class<?>... primarySources) {
// 传入的类叫做主要源,这也说明了它的重要性
this(null, primarySources);
}

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 检测应用类型”响应式、Servlet、普通应用
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 设置启动器
this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
// 设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 检测主类
this.mainApplicationClass = deduceMainApplicationClass();
}

新出现的类

  • WebApplicationType:一个枚举,包含三个值:SERVLETREACTIVENONE。用于决定应用是否需要启动特定类型的web服务器

  • Bootstrapper:用于初始化BootstrapRegistry

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface Bootstrapper {

    /**
    * Initialize the given {@link BootstrapRegistry} with any required registrations.
    * @param registry the registry to initialize
    */
    void intitialize(BootstrapRegistry registry);

    }
  • BootstrapRegistry:启动注册器,在服务启动阶段到ApplicationContext准备好这段时间有效;作用有两个:创建创建过程比较复杂的Bean、创建需要在ApplicationContext准备好之前共享的Bean。可以理解为预加载容器,即SpringBoot启动阶段使用的容器。

  • ApplicationContextInitializer:用于初始化ApplicationContext,调用时机在AbstractApplicationContext.refresh()之前。

    也就是说,在SpringBoot中,可以添加自己的ApplicationContextInitializer在容器初始化时修改内容。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

    /**
    * Initialize the given application context.
    * @param applicationContext the application to configure
    */
    void initialize(C applicationContext);

    }

获取工厂对象 - getSpringFactoriesInstances

听这个方法,像是抽象工厂模式,但总体看下来不大像,如果我们只是把它们当成一种插件机制,会更加方便理解。

getSpringFactoriesInstances()是贯穿SpringBoot启动的静态方法,用于加载指定类型的实例,来源是所有包下的META-INF/spring.factories文件中指定的类型。其作用就是获取指定类型的所有实现类的实例。

我们首先温习一下spring.factories文件长啥样

1
2
3
4
5
org.springframework.boot.env.EnvironmentPostProcessor=\
com.baomidou.mybatisplus.autoconfigure.SafetyEncryptProcessor
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration

然后再来看这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 获取指定类型的完整类名
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 创建它们
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 按照@Order注解排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

// 直接调用了反射创建实例
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}

理解上面那段代码的重点,又落在了SpringFactoriesLoader.loadFactoryNames(type, classLoader)上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// 注意这个spring.factories的位置
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryType, "'factoryType' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
// 关键方法,根据指定的工厂类型,获取其实现类们的名字
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
}
List<T> result = new ArrayList<>(factoryImplementationNames.size());
for (String factoryImplementationName : factoryImplementationNames) {
// 反射实例化这些工厂实现类
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
// 按照Order和Priority注解排序
AnnotationAwareOrderComparator.sort(result);
return result;
}

/**
* Load the fully qualified class names of factory implementations of the
* given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given
* class loader.
* <p>As of Spring Framework 5.3, if a particular implementation class name
* is discovered more than once for the given factory type, duplicates will
* be ignored.
* @param factoryType the interface or abstract class representing the factory
* @param classLoader the ClassLoader to use for loading resources; can be
* {@code null} to use the default
* @throws IllegalArgumentException if an error occurs while loading factory names
* @see #loadFactories
*/
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}

result = new HashMap<>();
try {
// 获取所有包下的 META-INF/spring.factories 文件
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
// 将spring.factories文件的内容加载成属性
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
// 值按逗号拆分
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
// 组装成key-list的形式
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
.add(factoryImplementationName.trim());
}
}
}

// Replace all lists with unmodifiable lists containing unique elements
result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
cache.put(classLoader, result);
}
catch (IOException ex) {
... ...
}
return result;
}

private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
try {
Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
// 反射实例化
return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
} catch (Throwable ex) {
... ...
}
}

检测WebApplicationType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" };

private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

// 要么是响应式应用、要么是Servlet应用、要么是普通应用
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}

检测逻辑

  • 类路径中只有org.springframework.web.reactive.DispatcherHandler时,是响应式应用
  • 类路径中同时存在javax.servlet.Servletorg.springframework.web.context.ConfigurableWebApplicationContext时,是Servlet应用
  • 否则,是普通应用

WebApplicationType有什么用

  • 创建environment时决定创建什么类型的Environment:private ConfigurableEnvironment getOrCreateEnvironment()
  • 创建ApplicationContext时指定具体类型

检测主类

1
2
3
4
5
6
7
8
9
10
11
12
13
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
} catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}

检测逻辑:从当前调用栈中,寻找main方法那一层,其所属类就是主类

run方法

这是应用启动的主要逻辑之所在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public ConfigurableApplicationContext run(String... args) {
// 秒表,仅作为启动时间记录用
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 创建默认的BootstrapContext,前面说了它是启动阶段的临时容器
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// SpringApplicationRunListener,专为SpringApplication启动的各个阶段准备的监听器
// 其实只有一个实现类EventPublishingRunListener,用于创建启动中的事件并广播出去
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 命令行参数封装起来
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 打印banner
Banner printedBanner = printBanner(environment);
// 创建容器
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备容器
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 刷新容器
refreshContext(context);
// 刷新容器的善后处理:默认为空
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 广播已开始事件
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}

try {
// 广播运行中事件
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}

获取SpringApplicationRunListener

1
2
3
4
5
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 从sprin.factories中获取SpringApplicationRunListener子类
return new SpringApplicationRunListeners(logger,getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);
}

准备环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// 创建environment对象
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置环境对象:添加conversionService和命令行参数
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 向环境中添加属性源:ConfigurationPropertySource
ConfigurationPropertySources.attach(environment);
// 广播环境准备好的消息
listeners.environmentPrepared(bootstrapContext, environment);
// 将默认属性移到属性源的最末尾,属性源的顺序很重要
DefaultPropertiesPropertySource.moveToEnd(environment);
// 将类中的profile加入environment的activeProfiles中,使得该profile生效
configureAdditionalProfiles(environment);
... ...
return environment;
}

// 不同的应用类型,需要创建不同的环境对象,前面分析ApplicationContext时说过不同环境对象的区别
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
// 处理ConversionService,前面分析ApplicationContext时说过该对象的作用,用于类型转换
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
// 配置属性源:将命令行参数加入属性源
configurePropertySources(environment, args);
// 没用
configureProfiles(environment, args);
}

创建ApplicationContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}

// 不言自明
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
switch (webApplicationType) {
case SERVLET:
return new AnnotationConfigServletWebServerApplicationContext();
case REACTIVE:
return new AnnotationConfigReactiveWebServerApplicationContext();
default:
return new AnnotationConfigApplicationContext();
}
} catch (Exception ex) {
... ...
}
};

准备容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 注入environment
context.setEnvironment(environment);
// 注入resourceLoader、classLoader、beanNameGenerator、conversionService
postProcessApplicationContext(context);
// 应用所有在构造方法中和set注入的ApplicationContextInitializer
applyInitializers(context);
// 广播事件
listeners.contextPrepared(context);
// 临时容器工作完成,关闭
bootstrapContext.close(context);
// 下面添加一些与SpringBoot相关的一些Bean
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// 获取加载源,即配置类所在源
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 从源加载Bean定义到容器中
load(context, sources.toArray(new Object[0]));
// 广播事件:Bean定义加载完成
listeners.contextLoaded(context);
}

其它 - 注解排序

为组件排序的方法,我们发现哪儿都有它,这里关照一下:AnnotationAwareOrderComparator.sort()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class AnnotationAwareOrderComparator extends OrderComparator {

public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();

public static void sort(List<?> list) {
if (list.size() > 1) {
// 将当前单例当做比较器传入
list.sort(INSTANCE);
}
}

// 这个在OrderComparator会调用到
protected Integer findOrder(Object obj) {
// 调用父类的方法获取order:实现Ordered接口就给出值
Integer order = super.findOrder(obj);
if (order != null) {
return order;
}
// 否则从注解中找
return findOrderFromAnnotation(obj);
}

@Nullable
private Integer findOrderFromAnnotation(Object obj) {
// 从@Order注解中取得排序值
AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
if (order == null && obj instanceof DecoratingProxy) {
return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
}
return order;
}

}

所以,重点肯定在OrderComparatorcompare()方法上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public int compare(@Nullable Object o1, @Nullable Object o2) {
return doCompare(o1, o2);
}

private int doCompare(@Nullable Object o1, @Nullable Object o2) {
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
// PriorityOrdered有短路作用,有实现PriorityOrdered的比没有实现的优先级低
if (p1 && !p2) {
return -1;
} else if (p2 && !p1) {
return 1;
}

// 二者都没有实现PriorityOrdered,则根据Ordered接口或@Order注解来
int i1 = getOrder(o1);
int i2 = getOrder(o2);
return Integer.compare(i1, i2);
}

protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = findOrder(obj);
if (order != null) {
return order;
}
}
// 没有实现任何顺序的优先级最低
return Ordered.LOWEST_PRECEDENCE;
}

protected Integer findOrder(Object obj) {
return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}

可以总结出优先级顺序,两个组件

  • 如果一个实现了PriorityOrdered接口,一个没有实现PriorityOrdered接口,则实现了这个优先级更高

    PriorityOrderedOrder的子接口,没有任何附加实现

    也就是说,PriorityOrdered就是想实现一点:它比普通Ordered接口具有更高的优先级

  • 如果都实现了PriorityOrdered,则根据其order值排序

  • 如果实现了Ordered或被@Order注解,则根据其order值排序

  • 没有任何排序接口或注解的组件之间相互对比,永远是相等的

  • 没有任何排序接口或注解的组件,和,有任意一个排序接口或注解的组件,后者优先级更高,除非后者主动指定order为Ordered.LOWEST_PRECEDENCE

留言

2021-12-07

⬆︎TOP